/*
 * Project: CareerAdmin
 * @(#)$Id: ApplicationSort.java,v 1.1 2006/09/21 22:05:17 jjohnston Exp $
 * 
 * This Software is confidential and copyrighted.
 * Copyright  2003, 2005 Room & Board, Inc.  All Rights Reserved.
 * 
 * This software is the proprietary information of Room & Board, Inc.  Use 
 * is subject to license terms.
 * 
 * Title to Software and all associated intellectual property rights is retained 
 * by Room & Board, Inc. and/or its licensors.
 * 
 * Except as specifically authorized in any Supplemental License Terms, this 
 * software may not be copied.  Unless enforcement is prohibited by 
 * applicable law, you may not modify, decompile, reverse engineer this 
 * Software without the express written permission of Room & Board, Inc.
 * 
 * No right, title or interest in or to any trademark, service mark, logo or 
 * trade name of Room & Board, Inc. or its licensors is granted under 
 * this Agreement.
 */
package com.perselab.recipe.dao.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.hibernate.Criteria;
import org.hibernate.criterion.Order;

/**
 * Creates a command to wrap the Hibernate criteria API to sort.
 * 
 * @since 2.0
 */
public class PersistentSort implements CriteriaCommand {
	/**
	 * Sort list
	 */
    List<Sort> sorts = new ArrayList<Sort>();
    List<Map> joinSorts = new ArrayList<Map>();

    /**
     * Adds sort
     * @param property
     * @param order
     */
    public void addSort(String property, String order) {
        sorts.add(new Sort(property, order));
    }
    
    /**
     * Adds join sort
     * @param path
     * @param alias
     * @param property
     * @param value
     */
    public void addJoinSort(String property, Object value){
    	Map map = new HashMap<String, String>();
    	map.put("value", value);
    	map.put("property", property);    	
    	
    	joinSorts.add(map);
    }

    /**
     * @see CriteriaCommand#execute(Criteria)
     */
    public Criteria execute(Criteria criteria) {
        for (Sort sort : sorts) {
            buildCriteria(criteria, sort.getProperty(), sort.getOrder());
        }
        
        for(Map joinSort : joinSorts){
        	Object value = joinSort.get("value");
        	String propertyName = (String) joinSort.get("property");
        	
        	if (value.equals(Sort.ASC)) {
        		criteria.addOrder(Order.asc(propertyName));
            } else if (value.equals(Sort.DESC)) {
                criteria.addOrder(Order.desc(propertyName));
            }
        	
        }

        return criteria;
    }
    
    /**
     * toHQL string
     * @return
     */
    public String toHQL(){
    	StringBuffer hql = new StringBuffer();
    	for (Sort sort : sorts) {
    		if(hql.length() != 0){
    			hql.append(",");
    		}
    		hql.append(" ").append(sort.property).append(" ").append(sort.order);
    	}
    	
    	for(Map joinSort : joinSorts){
        	Object value = joinSort.get("value");
        	String propertyName = (String) joinSort.get("property");
        	
        	if(hql.length() != 0){
    			hql.append(",");
    		}
        	
        	hql.append(" ").append(propertyName).append(" ").append(value);
        }
    	
    	return hql.toString();
    }

    /**
     * Build criteria
     * @param criteria
     * @param property
     * @param order
     */
    private void buildCriteria(Criteria criteria, String property, String order) {
        if (order.equals(Sort.ASC)) {
            criteria.addOrder(Order.asc(property));
        } else if (order.equals(Sort.DESC)) {
            criteria.addOrder(Order.desc(property));
        }
    }
    
    /**
     * Sort class, holding property name and sort type
     *
     */
    private static class Sort {
    	/** ascent*/
        public final static String ASC = "asc";
        /** descent*/
        public final static String DESC = "desc";

        /** property name*/
        private final String property;
        /** sort type*/
        private final String order;

        /**
         * Constructor
         * @param property
         * @param order
         */
        public Sort(String property, String order) {
            this.property = property;
            this.order = order;
        }

        /**
         * Gets property
         * @return
         */
        public String getProperty() {
            return property;
        }

        /**
         * Gets order
         * @return
         */
        public String getOrder() {
            return order;
        }
    }
}
